package parser;

import java.util.ArrayList;
import java.util.List;

import javax.swing.table.DefaultTableModel;
import storage.DataAccessManager;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.*;

public class FromItemParser implements FromItemVisitor
{
	private DefaultTableModel model;
	private String databaseName;
	private String alias;
	public FromItemParser(String databaseName)
	{
		this.databaseName = databaseName;
	}
	
	public DefaultTableModel getTableModel(FromItem formItem)
	{
		model = new DefaultTableModel();
		alias = formItem.getAlias();
		formItem.accept(this);
		return model;
	}
	@Override
	public void visit(Table table) 
	{
		DataAccessManager data = new DataAccessManager();
		entity.Table tableEntity = data.getDatabaseByName(databaseName).getTableByName(table.getWholeTableName());
		for (int i=0;i<tableEntity.getColumnsCount();i++)
		{
			entity.Column columnEntity= tableEntity.getColumnAt(i);
			if (alias==null) model.addColumn(tableEntity.getName()+"."+columnEntity.getName());
			else model.addColumn(alias+"."+columnEntity.getName());
		}
		
		for (int i=0;i<tableEntity.getRowCount();i++)
		{
			ArrayList<String> dataList = new ArrayList<String>();
			for (int j=0;j<tableEntity.getColumnsCount();j++) 
				dataList.add(tableEntity.getColumnAt(j).getDataAt(i));
			model.addRow(dataList.toArray());
		}
			
	}

	@Override
	public void visit(SubSelect subSelect) 
	{
		SelectParser selectParser = new SelectParser(databaseName);
		model = selectParser.getModel(subSelect);
		if (subSelect.getAlias()!=null)
		{
			DefaultTableModel tempModel = new DefaultTableModel();
			for (int i=0;i<model.getColumnCount();i++) tempModel.addColumn(subSelect.getAlias()+'.'+model.getColumnName(i));
			for (int i=0;i<model.getRowCount();i++)
			{
				List<String> values = new ArrayList<String>();
				for (int j=0;j<tempModel.getColumnCount();j++) 
					if (model.getValueAt(i, j)!=null) values.add(model.getValueAt(i, j).toString());
					else values.add(null);
				tempModel.addRow(values.toArray());
			}
			model = tempModel;
		}
	}

	@Override
	public void visit(SubJoin subJoin) 
	{
		Join join = subJoin.getJoin();
		FromItemParser parser = new FromItemParser(databaseName);
		DefaultTableModel model1 = parser.getTableModel(subJoin.getLeft());
		DefaultTableModel model2 = parser.getTableModel(join.getRightItem());
		OnExpressionParser onParser = new OnExpressionParser();
		String joinMode;
		if (join.isFull()) joinMode="Full";
		else if (join.isInner()) joinMode="Inner";
		else if (join.isLeft()) joinMode="Left";
		else if (join.isNatural()) joinMode="Natural";
		else if (join.isOuter()) joinMode="Outer";
		else if (join.isRight()) joinMode="Right";
		else joinMode="Simple";
		if (join.getOnExpression()!=null) model = onParser.GetModel(join.getOnExpression(), model1, model2, joinMode);
		else 
		{
			for (int j=0;j<model1.getColumnCount();j++) model.addColumn(model1.getColumnName(j));
			for (int j=0;j<model2.getColumnCount();j++) model.addColumn(model2.getColumnName(j));
			
			for (int j=0;j<model1.getRowCount();j++)
			{
				for (int k=0;k<model2.getRowCount();k++)
				{
					List<String> values = new ArrayList<String>();
					for (int p=0;p<model1.getColumnCount();p++) values.add(model1.getValueAt(j, p).toString());
					for (int p=0;p<model2.getColumnCount();p++) values.add(model2.getValueAt(k, p).toString());
					model.addRow(values.toArray()); 
				}
			}
		}
	}

}
